from djongo import models

# Create your models here.


class MongoLogBase(models.Model):
    """日志基类"""
    id = models.ObjectIdField(db_column='_id')
    log_time = models.DateTimeField()
    objects = models.DjongoManager()

    class Meta:
        abstract = True

    def __str__(self):
        return '%s object (%s)' % (self.__class__.__name__, self.log_time)


class IPLocation(models.Model):
    """IP地理位置信息"""
    country_name = models.CharField(max_length=50)                  # 国家
    region_name = models.CharField(max_length=50)                   # 省/州
    city_name = models.CharField(max_length=50)                     # 城市
    owner_domain = models.CharField(max_length=50)                  # 所有者
    isp_domain = models.CharField(max_length=50)                    # 运营商
    latitude = models.CharField(max_length=20)                      # 纬度
    longitude = models.CharField(max_length=20)                     # 经度
    timezone = models.CharField(max_length=50)                      # 时区名称
    utc_offset = models.CharField(max_length=10)                    # UTC时差
    china_admin_code = models.CharField(max_length=20)              # 行政代码
    idd_code = models.CharField(max_length=10)                      # 国际区号
    country_code = models.CharField(max_length=10)                  # 国家代码
    continent_code = models.CharField(max_length=10)                # 大陆代码

    class Meta:
        abstract = True


class DeviceFingerprint(models.Model):
    """设备指纹信息"""
    device_model = models.CharField(max_length=256, null=True)      # 设备型号
    device_brand = models.CharField(max_length=256, null=True)      # 设备品牌
    system_version = models.CharField(max_length=256, null=True)    # 系统版本
    system_build = models.CharField(max_length=256, null=True)      # build版本号
    user_latitude = models.CharField(max_length=256, null=True)     # 纬度
    user_longitude = models.CharField(max_length=256, null=True)    # 经度
    android_id = models.CharField(max_length=256, null=True)
    serial_number = models.CharField(max_length=256, null=True)
    imei = models.CharField(max_length=256, null=True)
    imei_p = models.CharField(max_length=256, null=True)
    serial_number_p = models.CharField(max_length=256, null=True)
    uuid = models.CharField(max_length=256, null=True)


class CASLog(MongoLogBase):
    """CAS访问认证日志"""
    AUTH_TYPE_CHOICES = (
        ('SMS', '短信验证码登录'),
        ('REST_PASSWORD', 'WEB账号密码登录'),
        ('SDK_PASSWORD', 'SDK账号密码登录'),
        ('FINGER', '指纹登录'),
    )

    AUTH_RESULT_CHOICES = (
        ('AUTH_SUCCESS', '认证成功'),
        ('AUTH_FAIL', '认证失败'),
        ('LOGOUT_SUCCESS', '注销成功'),
        ('LOGOUT_FAIL', '注销失败'),
        ('AUTHORIZE_SUCCESS', '授权访问服务成功'),
        ('AUTHORIZE_FAIL', '授权访问服务失败'),
        ('VALIDATE_SUCCESS', '访问服务验证权限成功'),
        ('VALIDATE_FAIL', '访问服务验证权限失败'),
    )

    auth_type = models.CharField(                                   # 认证方式
        max_length=20,
        choices=AUTH_TYPE_CHOICES
    )
    resource = models.IntegerField(null=True)                       # 资源id
    auth_result = models.CharField(                                 # 认证结果
        max_length=20,
        choices=AUTH_RESULT_CHOICES
    )
    auth_code = models.IntegerField()                               # 认证状态码
    auth_time = models.DateTimeField()                              # 认证时间
    client_ip = models.GenericIPAddressField()                      # 认证IP
    username = models.CharField(max_length=100)                     # 用户账号
    url = models.URLField(max_length=256)                           # 认证原始service url
    request_source = models.IntegerField()                          # 请求来源
    ip_location = models.EmbeddedModelField(                        # IP地理位置信息
        model_container=IPLocation
    )
    device_fingerprint = models.EmbeddedModelField(                 # 设备指纹信息
        model_container=DeviceFingerprint
    )
    platform = models.IntegerField(default=1)     # 平台    1 移动端 2 客户端 3 web端 4 Linux
    strategy = models.CharField(max_length=100, null=True)     # 策略
    device = models.CharField(max_length=100, null=True)       # 设备型号
    device_uuid = models.CharField(max_length=32, null=True)    # device uuid


    class Meta:
        db_table = 'cas'


class StrategyMeta(models.Model):
    """策略元数据，包括策略名称、分值等"""
    name = models.CharField(max_length=20)                          # 策略名
    description = models.TextField()                                # 策略描述
    level = models.PositiveSmallIntegerField()                      # 策略危险等级
    weight = models.PositiveIntegerField()                          # 策略分值
    category = models.CharField(max_length=20)                      # 策略类型

    class Meta:
        abstract = True


class StrategyLog(MongoLogBase):
    """策略触发日志"""
    username = models.CharField(max_length=100)                     # 用户账号
    resource = models.IntegerField(null=True)                       # 相关资源id（如果有的话）
    uid = models.CharField(max_length=20)                           # 策略uid
    filename = models.CharField(max_length=256, null=True)          # 文件名（密级文件相关策略）
    md5 = models.CharField(max_length=32, null=True)                # 文件MD5（密级文件相关策略）
    secret_level = models.PositiveIntegerField(null=True)           # 涉密等级（密级文件相关策略）
    meta = models.EmbeddedModelField(model_container=StrategyMeta)
    url = models.URLField(max_length=256)                           # 认证原始service url
    client_ip = models.CharField(max_length=32, null=True)          #
    platform = models.IntegerField(null=True)                       # 渠道 相当于channel
    device_uuid = models.CharField(max_length=64, null=True)        # 设备uuid

    class Meta:
        db_table = 'strategy'


class EmailLog(MongoLogBase):
    """邮件日志"""
    protocol = models.CharField(max_length=10)                      # 协议类型
    login_user = models.CharField(max_length=256)                   # 登录用户名
    smtp_from = models.CharField(                                   # SMTP协议发件人
        max_length=256,
        null=True, blank=True
    )
    smtp_to = models.CharField(                                     # SMTP协议收件人
        max_length=256,
        null=True, blank=True
    )
    smtp_subject = models.CharField(                                # 邮件主题
        max_length=256,
        null=True, blank=True
    )
    filenames = models.ListField()                                  # 附件名称，允许多个
    filemd5s = models.ListField()                                   # 附件MD5，允许多个
    session_time = models.FloatField()                              # 协议会话耗时，单位为s
    pid = models.IntegerField()                                     # 日志输出的pid
    filelevels = models.ListField()                                 # 文件密级，允许多个
    sensitive_keyword = models.ListField()                          # 敏感词列表
    sensitive_keyword_matched_times = models.ListField()            # 敏感词命中次数列表
    xmailer = models.CharField(max_length=50)                       # 发件人使用的邮件客户端信息

    class Meta:
        db_table = 'email'


class EmbeddedDeviceInfo(models.Model):
    """apps日志中的device_info文档"""
    phone_number = models.CharField(max_length=20)
    device_model = models.CharField(max_length=100)
    imei = models.CharField(max_length=20)
    device_uuid = models.CharField(max_length=100, null=True)
    imsi = models.CharField(max_length=20)
    userName = models.CharField(max_length=100)
    mac_address = models.CharField(max_length=20)
    system_version = models.CharField(max_length=50)
    is_root = models.IntegerField()

    class Meta:
        abstract = True


class EmbeddedApps(models.Model):
    """apps日志中的apps_开头的文档"""
    md5 = models.CharField(max_length=32, null=True)
    package_name = models.CharField(max_length=256, null=True)
    program_name = models.CharField(max_length=100, null=True)
    apk_path = models.CharField(max_length=256, null=True)
    apk_version_name = models.CharField(max_length=20, null=True)
    apk_size = models.PositiveIntegerField(null=True)
    is_system_apps = models.IntegerField(null=True)
    virus_description = models.CharField(max_length=256, null=True)  # 病毒描述
    virus_name = models.CharField(max_length=256, null=True)  # 病毒名称

    class Meta:
        abstract = True


class AppsLog(MongoLogBase):
    """SDK的apps日志"""
    device_info = models.EmbeddedModelField(model_container=EmbeddedDeviceInfo)
    scan_mode = models.IntegerField()
    apps_danger = models.ArrayModelField(model_container=EmbeddedApps)
    apps_risk = models.ArrayModelField(model_container=EmbeddedApps)
    apps = models.ArrayModelField(model_container=EmbeddedApps)
    apps_sensitive = models.ArrayModelField(model_container=EmbeddedApps)
    apps_harmless = models.ArrayModelField(model_container=EmbeddedApps)
    device_uuid = models.CharField(max_length=32, null=True)

    class Meta:
        db_table = 'apps'


class FileLog(MongoLogBase):
    """文件类日志，包括下载/分享/邮件附件"""
    SOURCE_DOWNLOAD = 'download'
    SOURCE_SHARE = 'share'
    SOURCE_EMAIL = 'email'

    source = models.CharField(max_length=20)                        # 文件来源
    filename = models.CharField(max_length=256)                     # 文件名
    filesize = models.PositiveIntegerField()                        # 文件大小
    md5 = models.CharField(max_length=32)                           # 文件MD5
    sen_type = models.IntegerField(default=0)                       # 敏感类型，0无，1文件匹配，2关键字匹配，3相似度匹配
    sen_words = models.ListField()                                  # 敏感词
    sen_level = models.IntegerField(default=0)                      # 保密等级， 敏感等级，0无，1低，2中，3高
    username = models.CharField(max_length=100)                     # 用户名
    device = models.CharField(max_length=50)                        # 设备类型

    class Meta:
        db_table = 'files'


class ShareLog(MongoLogBase):
    """分享类日志"""
    type = models.CharField(max_length=20)                          # 分享类型
    method = models.CharField(max_length=50)                        # 分享方式
    url = models.CharField(max_length=256)                          # 分享链接
    filename = models.CharField(max_length=256)                     # 文件名
    username = models.CharField(max_length=100)                     # 用户名
    send_to = models.CharField(max_length=100)                      # 发送到？
    sen_level = models.IntegerField()                               # 保密等级

    class Meta:
        db_table = 'share'


class DynamicAttackLog(MongoLogBase):
    """动态攻击日志"""
    os_version = models.CharField(max_length=20)                    # 系统版本
    manufacture = models.CharField(max_length=20)                   # 制造商
    product = models.CharField(max_length=20)
    brand = models.CharField(max_length=20)
    model = models.CharField(max_length=20)
    device = models.CharField(max_length=20)
    imei = models.CharField(max_length=17)
    device_uuid = models.CharField(max_length=32, null=True)
    shell_version = models.CharField(max_length=20)                 # 加固的版本
    sdk_version = models.IntegerField()                             # app的sdk_version
    dynamic_attack = models.IntegerField()                          # 攻击类型代码
    attack_type = models.CharField(max_length=20)                   # 攻击类型名称
    mac = models.CharField(max_length=20)                           # MAC地址
    device_id = models.CharField(max_length=20)                     # 设备ID
    appname = models.CharField(max_length=50)                       # App的名称
    packagename = models.CharField(max_length=100)                  # App的包名


class UserActivityLog(MongoLogBase):
    """用户行为监控日志，数据来源于mongo的ztp"""
    username = models.CharField(max_length=100, null=True)          # 用户名
    resource = models.CharField(max_length=100, null=True)          # 应用id
    category = models.CharField(max_length=20)                      # 行为类别
    activity = models.CharField(max_length=100, null=True)          # 行为名称
    abnormal = models.BooleanField(default=False)                   # 是否为异常行为
    device_type = models.CharField(max_length=20, null=True)                   # 设备型号   huawei   xiaomi
    strategy = models.CharField(max_length=20, null=True)                      # 触发策略
    ip = models.CharField(max_length=20, null=True)
    city = models.CharField(max_length=20, null=True)
    url = models.URLField(max_length=256, null=True)                           # 认证原始service url
    platform = models.IntegerField(null=True)                                # 平台

    class Meta:
        db_table = 'user_activity'


class EmbeddedLoopholesRisk(models.Model):
    """loopholes_risk日志中的漏洞的文档"""
    code = models.CharField(max_length=128)  # 漏洞编号,唯一
    name = models.CharField(max_length=128)  # 漏洞名称
    desc = models.CharField(max_length=512)  # 漏洞描述
    level = models.PositiveIntegerField()  # 漏洞危害等级,1低危,2中危,3高危,4严重漏洞
    release_time = models.CharField(max_length=64)   # 漏洞发布时间/日期
    advice = models.CharField(max_length=256)  # 修复建议
    patch = models.CharField(max_length=256)  # 官方补丁地址

    class Meta:
        abstract = True


class LoopholesRiskLog(MongoLogBase):
    """风险漏洞表日志，数据来源于mongo的ztp"""
    device_uuid = models.CharField(max_length=100, null=True)          # 设备UUID
    date = models.CharField(max_length=100, null=True)          # 检测时间
    serious = models.ArrayModelField(model_container=EmbeddedLoopholesRisk)  # 严重漏洞
    high = models.ArrayModelField(model_container=EmbeddedLoopholesRisk)  # 高危漏洞
    medium = models.ArrayModelField(model_container=EmbeddedLoopholesRisk)  # 中危漏洞
    low = models.ArrayModelField(model_container=EmbeddedLoopholesRisk)  # 低危漏洞

    class Meta:
        db_table = 'loopholes_risk'


class EmbeddedProgramsRisk(models.Model):
    """programs_risk日志中的漏洞的文档"""
    hash = models.CharField(max_length=128)  # 哈希值
    name = models.CharField(max_length=128)  # 恶意代码名称
    category = models.CharField(max_length=512)  # 恶意代码类型
    path = models.CharField(max_length=256)  # 安装路径

    class Meta:
        abstract = True


class ProgramsRiskLog(MongoLogBase):
    """恶意代码风险表日志，数据来源于mongo的ztp"""
    device_uuid = models.CharField(max_length=100, null=True)          # 设备UUID
    date = models.CharField(max_length=100, null=True)          # 检测时间
    trojans = models.ArrayModelField(model_container=EmbeddedProgramsRisk)  # 木马
    infection = models.ArrayModelField(model_container=EmbeddedProgramsRisk)  # 感染式恶意代码
    worm = models.ArrayModelField(model_container=EmbeddedProgramsRisk)  # 蠕虫式
    hack = models.ArrayModelField(model_container=EmbeddedProgramsRisk)  # 黑客工具
    grey = models.ArrayModelField(model_container=EmbeddedProgramsRisk)  # 灰色软件
    risk = models.ArrayModelField(model_container=EmbeddedProgramsRisk)  # 风险软件
    rubbish = models.ArrayModelField(model_container=EmbeddedProgramsRisk)  # 垃圾软件
    others = models.ArrayModelField(model_container=EmbeddedProgramsRisk)  # 其他病毒

    class Meta:
        db_table = 'programs_risk'


class EmbeddedBasicSafety(models.Model):
    """basic_safety日志中的漏洞的文档"""
    name = models.CharField(max_length=256)  # 检测项
    result = models.CharField(max_length=128)  # 检测结果
    advice = models.CharField(max_length=512)  # 安全建议
    patch = models.CharField(max_length=256)  # 修复建议

    class Meta:
        abstract = True


class BasicSafetyLog(MongoLogBase):
    """安全基线表日志，数据来源于mongo的ztp"""
    device_uuid = models.CharField(max_length=100, null=True)          # 设备UUID
    date = models.CharField(max_length=100, null=True)          # 检测时间
    detection = models.ArrayModelField(model_container=EmbeddedBasicSafety)  # 全部应用

    class Meta:
        db_table = 'basic_safety'


class EmbeddedAttackDetection(models.Model):
    """attack_detection日志中的漏洞的文档"""
    attack_type = models.CharField(max_length=256)  # 入侵检测类型
    attack_name = models.CharField(max_length=128)  # 入侵检测名称
    desc = models.CharField(max_length=512)  # 入侵检测描述
    level = models.CharField(max_length=32)  # 威胁等级, 1低危,2中危,3高危
    rule = models.CharField(max_length=128)  # 违反规则
    rule_id = models.CharField(max_length=512)  # 违反规则ID
    advice = models.CharField(max_length=512)  # 处理建议

    class Meta:
        abstract = True


class AttackDetectionLog(MongoLogBase):
    """入侵检测表日志，数据来源于mongo的ztp"""
    device_uuid = models.CharField(max_length=100, null=True)          # 设备UUID
    date = models.CharField(max_length=100, null=True)          # 检测时间
    attack = models.ArrayModelField(model_container=EmbeddedAttackDetection)  # 全部应用

    class Meta:
        db_table = 'attack_detection'